<?php

namespace nimo\common\csv;

use DB;
use PDO;

class DatabaseInterceptor implements ExportInterceptor, ImportInterceptor {
    protected $connection_name = null;
    protected $table;
    protected $sql;
    protected $bindings;
    protected $converter;
    protected $batch_size = null;
    protected $batch_insert = 0;
    protected $batch_error = 0;
    protected $configs = array();
    private $datas = array();
    public function __construct($table, $converter, $configs = array()) {
        $this->table = $table;
        $this->converter = $converter;
        $this->sql = null;
        $this->bindings = array();
        $this->batch_size = isset($configs['batch_size']) ? $configs['batch_size'] : null;
        $this->configs['first_line_header'] = isset($configs['first_line_comment']) ? $configs['first_line_header'] : 'false';
        $this->connection_name = isset($configs['connection_name']) ? $configs['connection_name'] : '';
    }
    public function set_query($sql, $bindings = array()) {
        $this->sql = $sql;
        $this->bindings = $bindings;
    }
    protected function select_statement() {
        $sql = ($this->sql) ? $this->sql : 'select * from ' . $this->table;
        if (! empty($this->connection_name)) {
            return DB::connection($this->connection_name)->getPdo()->prepare($sql);
        }
        return DB::connection()->getPdo()->prepare($sql);
    }
    public function counts() {
        return array('batch_insert' => $this->batch_insert,'batch_error' => $this->batch_error);
    }
    public function export($exporter) {
        $stmt = $this->select_statement();
        $stmt->execute($this->bindings);
        // customized logic to write csv file
        if ($this->converter) {
            while ( $data = $stmt->fetch(PDO::FETCH_ASSOC) ) {
                // write data to csv file
                $exporter->export($this->converter->convert($data));
            }
        } else {
            while ( $data = $stmt->fetch(PDO::FETCH_ASSOC) ) {
                // write data to csv file
                $exporter->export($data);
            }
        }
        $stmt->closeCursor();
    }
    public function import($rowno, $csv_data) {
        if ($rowno === null) {
            // finish
            if (count($this->datas)) {
                DB::table($this->table)->insert($this->datas);
                $this->datas = array();
            }
            return;
        }

        if ($rowno === 0 && $this->configs['first_line_header']) {
            return;
        }

        $data = ($this->converter) ? $this->converter->convert($csv_data) : $csv_data;

        if (count($data) == 0) {
            $this->batch_error ++;
            return;
        }
        if ($this->batch_size === null) {
            $config = app('config');
            $max_bind_number = (isset($config['database.max_bind_number'])) ? $config['database.max_bind_number'] : 999;
            $this->batch_size = intval($max_bind_number / count($data)) - 1;
        }
        $this->datas[] = $data;
        $this->batch_insert ++;

        // write data to database
        if (count($this->datas) >= $this->batch_size) {
            DB::table($this->table)->insert($this->datas);
            $this->datas = array();
        }
    }
}
